/*
 * bw_FcgiRequest.h
 *
 *  Created on: 2018年9月3日
 *  Author: Degang.Wu (windragon@126.com)
 *  Desc:
 */

#ifndef BW_FCGIREQUEST_H_
#define BW_FCGIREQUEST_H_

#include "bw_public.h"
#include "fcgio.h"

namespace bwcgi
{

#define DEAL_BUF_LEN 1024
#define SIGN_CODE_LEN 100
#define FILE_NAME_LEN 256

enum
{
    STATE_START,
    STATE_GET_SIGN_CODE,
    STATE_GET_FILE_NAME,
    STATE_GET_FILE_START,
    STATE_GET_FILE_CONTENT,
    STATE_CHECK_END,
    STATE_END
};

class FcgiRequest;

typedef const char*(*bwHttpHandle)(FcgiRequest* pFcgiReq);

class FcgiRequest
{
public:
	FcgiRequest(const FCGX_Request& _request);
	virtual ~FcgiRequest();

	void handleRequest();

	// get Body content
	const char* getBody() const;

	//get Body content length
	size_t getBodyLen();

	/*
	 * get query param
	 * 	a=1&b=2&c=3
	 * 	getQuery("a"), return "1"
	 */
	const char* getQuery(const char* key);

	const char* getUploadfile();
	U32	getUploadfileLen();

	int	setDownloadfile(const char* fname, const char* rename = NULL);
	void enableDown();

	const char* getRemoteAddr();
	int getRemotePort();
	const char* getMethod();
	const char* getUserAgent();
	const char* getURI();
	const char* getMimetype();
	const char* getBoundary();

	static void registeHandle(bwHttpHandle _handler);
	static void registeHandle(const char* uri, bwHttpHandle _handler);
	static void setDebug(int _debug);
	static bool isDebug();

protected:
	void readBody(const FCGX_Request& _request);
	void readBody_plain(const FCGX_Request& _request);
	void readBody_bin(const FCGX_Request& _request);

	void parseReq();

	void response(const char* sResp, const char* mime_type = "text/plain");
//	void response_binary(U8* buf, int buflen, const char* mime_type = "text/plain");

	const char* getQueryString();
	const char* getParam(const char* key);

	const char* getBaseUri();
	const char* getPathinfo();

	static const char* defaultHandler(FcgiRequest* pFcgiReq);

private:
	FCGX_Request request;
	std::string sBody;
	std::map<std::string, std::string> serverVars;
	std::map<std::string, std::string> querys;

	static bwHttpHandle handler;
	static int			 bDebug;

	U8*					pBuffer;
	U32					iBufferLen;

	std::string			sBoundary;

	std::string			sUploadfile;

	std::string			sDownloadfile;
	std::string			sDownRename;
	bool				bEnableDown;
	U8*					pDownBuf;

	static std::map<std::string, bwHttpHandle>	routers;
};

/*
 * 放弃，不建议再使用，请使用新版本的路由机制
 */
attribute_deprecated
void 	registeHttpHandle(bwHttpHandle _handler);

/*
 * 新版路由机制，可注册多个，uri起始部分需要相同（与lighttpd配置相互配合）
 */
void 	registeHttpHandle(const char* uri, bwHttpHandle _handler);

void	setDebug(int _debug = 0);

#define cgi_debug(format, ...) \
		_cgi_debug("[%s %d:%s] " \
		format, \
		__FILE__, __LINE__, __func__, ##__VA_ARGS__ )
int 	_cgi_debug(const char *format, ...);

} /* namespace bwcgi */

#endif /* BW_FCGIREQUEST_H_ */
